package xyz.zq.sf.common.security.component;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.authentication.BearerTokenExtractor;
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

/**
 * 资源服务配置
 * 1. 支持remoteTokenServices 负载均衡
 * 2. 支持 获取用户全部信息
 * 3. 接口对外暴露，不校验 Authentication Header 头
 *
 * @author hzq
 * @date 2021-01-28 18:00
 */
public class ResourceServerSecurityConfigurerAdapter extends ResourceServerConfigurerAdapter {

    /*允许所有网址属性*/
    @Autowired
    private PermitAllUrlProperties urlProperties;

    /*远程令牌服务*/
    @Autowired
    protected RemoteTokenServices remoteTokenServices;

    /*资源验证例外入口点*/
    @Autowired
    protected ResourceAuthExceptionEntryPoint resourceAuthExceptionEntryPoint;

    /*O Auth 2访问资源拒绝处理程序*/
    @Autowired
    private OAuth2AccessResourceDeniedHandler oAuth2AccessResourceDeniedHandler;

    /*承载令牌提取器*/
    @Autowired
    private BearerTokenExtractor bearerTokenExtractor;

    @Autowired
    private RestTemplate lbRestTemplate;

    /**
     * 资源配置
     */
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {

        /*默认访问令牌转换器*/
        DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();

        /*默认用户身份验证转换器*/
        DefaultUserAuthenticationConverter authenticationConverter = new DefaultUserAuthenticationConverter();

        /*设置用户令牌转换器*/
        accessTokenConverter.setUserTokenConverter(authenticationConverter);

        /*设置访问令牌转换器*/
        remoteTokenServices.setAccessTokenConverter(accessTokenConverter);

        /*设置Rest模板 实现@LoadBalanced 负载均衡*/
        remoteTokenServices.setRestTemplate(lbRestTemplate);

        resources.authenticationEntryPoint(resourceAuthExceptionEntryPoint)
                .tokenExtractor(bearerTokenExtractor)
                .accessDeniedHandler(oAuth2AccessResourceDeniedHandler)
                .tokenServices(remoteTokenServices);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {

        /*允许使用iframe 嵌套，避免swagger-ui 不被加载的问题*/
        http.headers().frameOptions().disable();

        /*
         * 禁用csrf攻击
         * 开启cors跨域
         */
        http.csrf().disable().cors().configurationSource(corsConfigurationSource());

        /*添加不需要认证的url*/
        http.authorizeRequests()
                .antMatchers(urlProperties.getUrls().stream().toArray(String[]::new))
                .permitAll()
                .anyRequest()
                .authenticated();
    }

    /**
     * 跨域源配置
     */
    private CorsConfigurationSource corsConfigurationSource() {
        UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
        return corsConfigurationSource;
    }
}
